package fr.afcepf.atod.util.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.util.List;

import javax.sql.DataSource;

import org.hibernate.Criteria;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.omg.CORBA.portable.ApplicationException;

/**
 * Interface qui défini les opérations sur les objets du domaine
 * pour les daos.
 * 
 * @author garribas
 * @version $Revision: 1.19 $
 */
public interface IDao {
	/**
	 * Obtenir un objet du domaine à partir de la clé primaire.
	 * @param _id objet qui représente la clé primaire
	 * @return l'objet du domaine retrouvé
	 * @throws ObjectNotFoundException si l'objet demandé n'existe pas
	 */
	Object load(final Serializable _id) throws ObjectNotFoundException;

	/**
	 * Enregistrer un objet du domaine en base.
	 * @param _obj l'objet à enregistrer
	 */
	void create(final Object _obj);

	/**
	 * Modifier un objet du domaine.
	 * @param _obj l'objet à modifier
	 */
	void update(final Object _obj);

	/**
	 * Créer ou Modifier un objet du domaine.
	 * @param _obj l'objet à modifier
	 */
	void saveOrUpdate(final Object _obj);

	/**
	 * Supprimer un objet du domaine.
	 * @param _obj l'objet à supprimer
	 */
	void delete(final Object _obj);
	
	/**
	 * Supprimer un objet du domaine à partir de sa clé primaire.
	 * @param _id objet qui représente la clé primaire
	 */
	void delete(final Serializable _id);

	/**
	 * Obtient tous les objets du domaine d'un certain type.
	 * 
	 * @return une liste d'objets du domaine
	 */
	List<?> findAll();

	/**
	 * Flush le travail en cours 
	 */
	void flush();
	
	/**
	 * Copie l'état de l'objet dans l'objet persistant qui a le même 
	 * identificateur.
	 * Semblable à un update mais permter d'éviter les NonUniqueObjectException
	 * quand un objet a été lu dans une session hibernate et ensuite on veut 
	 * sauvegarder un objet qui a le même identificateur.
	 * @param _obj l'objet à sauvagarder
	 * @return l'objet persistant acutalisé
	 */
	Object merge(final Object _obj);
	
	/**
	 * Exécution d'un UPDATE, INSERT ou DELETE sql,
	 * utlisation d'un <code>java.sql.Statement</code> .
	 * 
	 * @param _sql la requête sql
	 * @return le nombre d'enregistrements affectés par la requête
	 */
	int executeSqlUpdate(final String _sql);
	
	/**
	 * Exécution d'un UPDATE, INSERT ou DELETE sql,
	 * utlisation d'un <code>java.sql.PreparedStatement</code> .
	 * 
	 * @param _sql la requête sql avec des paramètres (?)
	 * @param _params la liste de paramètres pour la requête
	 * @return le nombre d'enregistrements affectés par la requête
	 */
	int executeSqlUpdate(final String _sql, final Object[] _params);
	
	/**
	 * Execute requete Hibernate Update
	 * @param _queryString
	 * @param _paramNames
	 * @param _params
	 * @return
	 */
	int executeHibernateUpdate(final String _queryString, final String[] _paramNames, final Object[] _params);
	
	/**
	 * Crée un objet Query
	 * 
	 * @param hqlQuery
	 * @return
	 * @throws ApplicationException
	 */
	Query createQuery(String hqlQuery);

	/**
	 * Crée un objet SQLQuery
	 * 
	 * @param sqlQuery
	 * @return
	 * @throws ApplicationException
	 */
	SQLQuery createSQLQuery(String sqlQuery);
	
	/**
	 * Crée un objet Query pour pagination
	 * 
	 * @param _hqlQuery
	 * @param _paramNames
	 * @param _paramValues
	 * @param page - commence à partie de 1
	 * @param pageSize
	 * @return
	 * @throws ApplicationException
	 */
	List<?> executeHQLQueryWithPagination(String _hqlQuery,String[] _paramNames, Object[] _paramValues, int page, int pageSize);

	/**
	 * Crée un objet SQLQuery pour pagination
	 * 
	 * @param _sqlQuery
	 * @param _paramNames
	 * @param _paramValues
	 * @param page
	 * @param pageSize
	 * @return
	 * @throws ApplicationException
	 */
	List<?> executeSQLQueryWithPagination(String _sqlQuery,String[] _paramNames, Object[] _paramValues, int page, int pageSize);
	
	/**
	 * 
	 * @param _hqlQuery
	 * @return
	 * @throws ApplicationException
	 */
	public int executeHqlUpdateQuery(String _hqlQuery) throws ApplicationException;
	
	/**
	 * 
	 * @param _hqlQuery
	 * @param _paramNames
	 * @param _paramValues
	 * @param page
	 * @param pageSize
	 * @return
	 * @throws ApplicationException
	 */
	public int executeHqlUpdateQuery(String _hqlQuery,String[] _paramNames, Object[] _paramValues);
	
	/**
	 * 
	 * @param _sqlQuery
	 * @return
	 * @throws ApplicationException
	 */
	public int executeSqlUpdateQuery(String _sqlQuery);
	
	/**
	 * 
	 * @param _sqlQuery
	 * @param _paramNames
	 * @param _paramValues
	 * @param page
	 * @param pageSize
	 * @return
	 * @throws ApplicationException
	 */
	public int executeSqlUpdateQuery(String _sqlQuery,String[] _paramNames, Object[] _paramValues);
	
	/**
	 * 
	 * @param _persistentClass
	 * @return
	 */
	Criteria createCriteria(Class<?> _persistentClass);
	
	Long getMaxId(String _entityName);
	
	/**
	 * Verifier l'existence de l'objet de type _class qui a le _columnName qui vaut _valeur 
	 * retourne false si l'objet n'existe pas
	 * 			true si l'objet existe
	 * @param _class
	 * @param _columnName
	 * @param _valeur
	 * @return
	 */
	public boolean existEntity(Class<?> _class,String _columnName,Object _valeur);
	
	public void evictObjectsFromSession(List<?> objs);
	
	public void clearSession();
	
	public DataSource getSlaveDataSource();
	public void setSlaveDataSource(DataSource dataSource);
	
	public Connection getConnection();
	public boolean isMasterDS();
	
	int executeHibernateUpdate(String _sqlQuery);
	
}